package com.vecspace.middleplatform.filemanagment.httphandler;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;

import com.vecspace.middleplatform.filemanagment.pojo.UploadFile;
import com.vecspace.middleplatform.filemanagment.pojo.UploadFileSimple;
import com.vecspace.middleplatform.filemanagment.service.UploadFileService;
import com.vecspace.security.model.LoginContext;
import com.vecspace.utils.Assert;
import com.vecspace.utils.TJSON;
import com.vecspace.utils.UUIDUtil;
import com.vecspace.web.HttpContentType;
import com.vecspace.web.servlet.model.BaseController;
import com.vecspace.web.servlet.model.FtlViewModel;
import com.vecspace.web.servlet.model.HttpHandler;
import com.vecspace.web.servlet.model.NullValue;
import com.vecspace.web.servlet.model.Param;
import com.vecspace.web.servlet.model.Path;
import com.vecspace.web.servlet.model.ViewModel;

/**
 * 
 * 功能描述 
 * @类型名称 CommonFileUploadHandler
	* @author wanghua
 */
@HttpHandler //commonUploadHandler
public class FileTransferHandler extends BaseController{
	@Autowired
	private UploadFileService uploadFileService;

	/**实现文件的上传，并将上传文件信息记录到数据库中*/
	@Path("uploadFile")
	public Object uploadFile(HttpServletRequest request,HttpServletResponse response,
			@Param("appId")String appId, @Param("tenantId") Long tenantId, @Param("classifyCode1")String classifyCode1, @Param("classifyCode2")String classifyCode2,
			@Param("thumbnail1Width")int thumbnail1Width, @Param("thumbnail1Height")int thumbnail1Height, 
			@Param("thumbnail2Width")int thumbnail2Width, @Param("thumbnail2Height")int thumbnail2Height) throws Exception {
		List<Object> result = new ArrayList<Object>();
		String loginId = getLoginId(request);
		if(tenantId == null) {
			tenantId = LoginContext.getTenantId();
		} 
		List<UploadFile> uploadFiles = uploadFileService.uploadFiles(request, appId, tenantId, classifyCode1, classifyCode2, thumbnail1Width, thumbnail1Height, thumbnail2Width, thumbnail2Height, loginId);
		for (UploadFile uploadFile : uploadFiles) {
			Map<String,Object> fileInfo = new HashMap<String,Object>();
			fileInfo.put("fileName", uploadFile.getOrgFileName());
			fileInfo.put("id", uploadFile.getId());
			fileInfo.put("accessId", uploadFile.getAccessId());
			fileInfo.put("fileSize", uploadFile.getFileBytes());
			result.add(fileInfo);
		}

		response.setContentType("text/json;charset=utf-8");
		response.setHeader("Pragma", "No-cache");
		response.setDateHeader("Expires", 0);
		response.setHeader("Cache-Control", "no-cache");
		String resultString = TJSON.toJSONString(result);
		PrintWriter out = response.getWriter();
		out.println(resultString);
		out.flush();
		out.close();

		return NullValue.value;
	}

	/**
	 * 上传行为分析图片（无需登录）
	 * @param request
	 * @param response
	 * @param tenantId
	 * @return
	 * @throws Exception
	 */
	@Path("uploadCameraPhotoFile")
	public Object uploadCameraPhotoFile(HttpServletRequest request,HttpServletResponse response, @Param("tenantId") Long tenantId) throws Exception {
		return this.uploadFile(request, response, "bim", tenantId, "CameraPhoto", "BG_NVR", 0, 0, 0, 0);
	}

	@Path("uploadImportTempFile")
	public Object uploadImportTempFile(HttpServletRequest request,HttpServletResponse response,
							 @Param("appId")String appId, @Param("tenantId") Long tenantId) throws Exception {
		return this.uploadFile(request, response, appId, tenantId, "import", "temp", 0, 0, 0, 0);
	}

	@Path("uploadBase64Img")  
	public Object uploadBase64Img(HttpServletRequest request,HttpServletResponse response,@Param("base64Str")String base64Str,@Param("imgName")String imgName,
			@Param("appId")String appId, @Param("tenantId")Long tenantId, @Param("classifyCode1")String classifyCode1, @Param("classifyCode2")String classifyCode2,
			@Param("thumbnail1Width")int thumbnail1Width, @Param("thumbnail1Height")int thumbnail1Height, 
			@Param("thumbnail2Width")int thumbnail2Width, @Param("thumbnail2Height")int thumbnail2Height) throws Exception {
		//data:image/jpeg;base64,
		List<Object> result = new ArrayList<Object>();
		String loginId = getLoginId(request);
		if (StringUtils.isBlank(imgName)) {
			imgName = UUIDUtil.createUUID() + ".jpeg";
		}
		if(tenantId == null) {
			tenantId = LoginContext.getTenantId();
		}
		UploadFile uploadFile = uploadFileService.uploadBase64Img(request, base64Str, imgName, 
				appId, tenantId, classifyCode1, classifyCode2, 
				thumbnail1Width, thumbnail1Height, thumbnail2Width, thumbnail2Height, loginId);

		Map<String,Object> fileInfo = new HashMap<String,Object>();
		fileInfo.put("fileName", imgName);
		fileInfo.put("id", uploadFile.getId());
		fileInfo.put("accessId", uploadFile.getAccessId());
		fileInfo.put("fileSize", uploadFile.getFileBytes());
		result.add(fileInfo);  

		response.setContentType("text/json;charset=utf-8");
		response.setHeader("Pragma", "No-cache");
		response.setDateHeader("Expires", 0);
		response.setHeader("Cache-Control", "no-cache");
		String resultString = TJSON.toJSONString(result);
		try(PrintWriter out = response.getWriter()){
			out.println(resultString);
			out.flush();
		}
		return NullValue.value;
	}

	// 注册一个spring的编辑器非常重要，没有这个方法，上传将不能进行
	protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws ServletException {
		binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
	}
	/**下载文件（登录的情况下才能访问）
	 * rest/file/commonUploadHandler/downloadFile?id=402883c355948f0701559592ee770007
	 * @param request
	 * @param response
	 * @param id
	 * @return
	 * @throws Exception 
	* @author wanghua
	 */
	@Path(value="downloadFile", httpGet=true)
	@ResponseBody
	public String downloadFile(HttpServletRequest request,HttpServletResponse response,@Param("id")String id) throws Exception {
		Assert.throwz(id != null && id.length() > 0, "参数id不能为空");
		UploadFile uploadFile = uploadFileService.getUploadFile(id);
		Assert.throwz(uploadFile != null, "文件id不存在："+id);
		return downloadFile(response, uploadFile);
	}

	/**用于没有登录时下载文件
	 * 
	 * @param request
	 * @param response
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@Path(value="file", httpGet=true)
	@ResponseBody
	public String downloadFile2(HttpServletRequest request,HttpServletResponse response,@Param("id")String id) throws Exception {
		Assert.throwz(id != null && id.length() > 0, "参数id不能为空");
		UploadFile uploadFile = uploadFileService.getUploadFile(id);
		Assert.throwz(uploadFile != null, "文件id不存在："+id);
		return downloadFile(response, uploadFile);
	} 

	@Path("downloadFileAccessId")
	@ResponseBody
	public String downloadFileAccessId(HttpServletRequest request,HttpServletResponse response,@Param("accessId")String accessId) throws Exception {
		Assert.throwz(accessId != null && accessId.length() > 0, "参数accessId不能为空");
		UploadFile uploadFile = uploadFileService.getUploadFileByAccessId(accessId);
		Assert.throwz(uploadFile != null, "文件不存在,accessId："+accessId);
		return downloadFile(response, uploadFile);
	}

	private String downloadFile(HttpServletResponse response, UploadFile uploadFile)
			throws Exception, IOException, FileNotFoundException, UnsupportedEncodingException {
		String message;
		File file = uploadFileService.getFile(uploadFile);
		if(!file.exists()){
			response.sendError(404,"File not found!");
			return "File not found!";
		}
		BufferedInputStream br = new BufferedInputStream(new FileInputStream(file));
		try{
			byte[] buf = new byte[1024];
			int len = 0;

			response.reset(); //非常重要
			response.setContentType("application/x-msdownload"); 
			String orgFileName = uploadFile.getOrgFileName();
			if(orgFileName == null) orgFileName = "";
			response.setHeader("Content-Disposition", "attachment; filename=" + new String(orgFileName.getBytes("gb2312"), "ISO8859-1" )); 
			OutputStream out = response.getOutputStream();
			try{
				while((len = br.read(buf)) >0){
					out.write(buf,0,len);
				}
			}finally{
				out.close();
			}
		}finally{
			br.close();
		}
		message = "success";

		return message;
	} 

	/**在线查看图片（登录的情况下才能访问）
	 * rest/file/commonUploadHandler/image?id=402883c355948f0701559592ee770007
	 * @param request
	 * @param response
	 * @param id
	 * @param sw 缩略图大小 widthxheight,比如 200X150
	 * @return
	 * @throws Exception 
	* @author wanghua
	 */
	@Path(value="image", httpGet=true)
	@ResponseBody
	public String image(HttpServletRequest request,HttpServletResponse response,@Param("id") String id, @Param("sw") String sw) throws Exception {
		Assert.throwz(id != null && id.length() > 0, "参数id不能为空");
		UploadFile uploadFile = uploadFileService.getUploadFile(id);
		Assert.throwz(uploadFile != null, "文件id不存在："+id);
		return createOrGetImage(response, uploadFile, sw);
	}

	/**在线查看图片（用于没有登录时访问图片）
	 * rest/file/commonUploadHandler/image?id=402883c355948f0701559592ee770007
	 * @param request
	 * @param response
	 * @param id
	 * @param sw 缩略图大小 widthxheight,比如 200X150
	 * @return
	 * @throws Exception 
	* @author wanghua
	 */
	@Path(value="img", httpGet=true)
	@ResponseBody
	public String image2(HttpServletRequest request,HttpServletResponse response,@Param("id") String id, @Param("sw") String sw) throws Exception {
		Assert.throwz(id != null && id.length() > 0, "参数id不能为空");
		UploadFile uploadFile = uploadFileService.getUploadFile(id);
		Assert.throwz(uploadFile != null, "文件id不存在："+id);
		return createOrGetImage(response, uploadFile, sw);
	}

	@Path(value="imageByAccessId", httpGet=true)
	@ResponseBody
	public String imageByAccessId(HttpServletRequest request,HttpServletResponse response,@Param("accessId") String accessId, @Param("sw") String sw) throws Exception {
		Assert.throwz(accessId != null && accessId.length() > 0, "参数accessId不能为空");
		UploadFile uploadFile = uploadFileService.getUploadFileByAccessId(accessId);
		Assert.throwz(uploadFile != null, "文件不存在,accessId："+accessId);
		return createOrGetImage(response, uploadFile, sw);
	}

	private String createOrGetImage(HttpServletResponse response, UploadFile uploadFile, String sw)
			throws Exception, IOException, FileNotFoundException {
		String message;
		File file;
		String contentType = HttpContentType.IMAGE_JPG;

			if("1".equals(sw)) {
				file = uploadFileService.createOrGetThumbnailFile(uploadFile, 1);
				contentType = HttpContentType.IMAGE_JPG;
			}else if("2".equals(sw)) {
				file = uploadFileService.createOrGetThumbnailFile(uploadFile, 2);
				contentType = HttpContentType.IMAGE_JPG;
			}else if(StringUtils.contains(sw, "x") || StringUtils.contains(sw, "X")){
				String[] arr = sw.split("x|X");
				int width = Integer.parseInt(arr[0]);
				int height = Integer.parseInt(arr[1]);
				file = uploadFileService.createOrGetThumbnailFile(uploadFile, width, height);
				contentType = HttpContentType.IMAGE_JPG;
			}else {
				file = uploadFileService.getFile(uploadFile);
				contentType = uploadFileService.getImageContentType(uploadFile);
			}

			if(!file.exists()){
				response.sendError(404,"File not found!");
				return "File not found!";
			}
			BufferedInputStream br = new BufferedInputStream(new FileInputStream(file));
			try{
				byte[] buf = new byte[1024];
				int len = 0;
				response.reset(); //非常重要

				response.setContentType(contentType);
				response.setHeader("Content-Disposition", "inline; filename="+file.getName());

				OutputStream out = response.getOutputStream();
				try{
					while((len = br.read(buf)) >0){
						out.write(buf,0,len);
					}
				}finally{
					out.close();
				}
			}finally{
				br.close();
			}
			message = "success";

		return message;
	}

	@Path(value="getFilesInfo", httpGet=true)
	public Map<String, List<UploadFileSimple>> getFilesInfo(@Param("ids")String ids)throws Exception{
		Map<String, List<UploadFileSimple>> map = new HashMap<>();
		if(StringUtils.isBlank(ids)) {
			return map;
		}else {
			String[] idArray=ids.split(";|,");
			List<UploadFileSimple> fileList = uploadFileService.getUploadFileListByIds(idArray);
			map.put("Rows", fileList);
		}		
		return map;
	}

	@Path(value="getFileInfo", httpGet=true)
	public UploadFile getUploadFileInfo(@Param("id")String id)throws Exception{
		Assert.throwz(id != null && id.length() > 0, "参数id不能为空");
		UploadFile uploadFile = uploadFileService.getUploadFile(id);
		Assert.throwz(uploadFile != null, "文件id不存在："+id);
		return uploadFile; 
	}

	private String getLoginId(HttpServletRequest request) {
		String loginId = "";
		HttpSession httpSession = request.getSession();
		if(httpSession != null) {
			Object loginIdObj = httpSession.getAttribute("loginId");
			if(loginIdObj != null) {
				loginId = loginIdObj.toString();
			}
		}
		return loginId;
	}

	/**
	 * 已上传文件文件重命名接口
	 * @param id
	 * @param name
	 * @return
	 * @throws Exception 
	 * @reviewer: 
	 */
	@Path("updateUploadFileName")
	public String updateUploadFileName(@Param("id")String id, @Param("name")String name) throws Exception {
		return uploadFileService.updateUploadFileName(id, name);
	}

	/**从磁盘和数据库记录中删除附件
	 * 
	 * @param id
	 * @return
	 * @throws Exception 
	 * @author wanghua
	 * @reviewer: 
	 */
	@Path("deleteUploadFile")
	public int deleteUploadFile(@Param("id")String id) throws Exception {
		return uploadFileService.deleteUploadFile(id);
	}

	/**从磁盘和数据库记录中删除附件多个
	 * 
	 * @param ids
	 * @return
	 * @throws Exception 
	 * @reviewer: 
	 */
	@Path("deleteUploadFiles")
	public int deleteUploadFile(@Param("ids") List<String> ids) throws Exception {
		int count = 0;
		for(String id : ids) { 
			count += uploadFileService.deleteUploadFile(id);
		}
		return count;
	}
	/**
	 * base64编码文件上传
	 * @param request
	 * @param response
	 * @param base64Str
	 * @param imgName
	 * @param appId
	 * @param tenantId
	 * @param classifyCode1
	 * @param classifyCode2
	 * @param thumbnail1Width
	 * @param thumbnail1Height
	 * @param thumbnail2Width
	 * @param thumbnail2Height
	 * @return
	 * @throws Exception
	 */
	@Path("uploadBase64ImgTemp")  
	public Object uploadBase64ImgTemp(HttpServletRequest request,HttpServletResponse response,@Param("base64Str")String base64Str,@Param("imgName")String imgName,
			@Param("appId")String appId, @Param("tenantId")Long tenantId, @Param("classifyCode1")String classifyCode1, @Param("classifyCode2")String classifyCode2,
			@Param("thumbnail1Width")int thumbnail1Width, @Param("thumbnail1Height")int thumbnail1Height, 
			@Param("thumbnail2Width")int thumbnail2Width, @Param("thumbnail2Height")int thumbnail2Height) throws Exception {
		//data:image/jpeg;base64,
		List<Object> result = new ArrayList<Object>();
		String loginId = getLoginId(request);
		if (StringUtils.isBlank(imgName)) {
			imgName = UUIDUtil.createUUID() + ".jpeg";
		}
		if(tenantId == null) {
			tenantId = LoginContext.getTenantId();
		}
		UploadFile uploadFile = uploadFileService.uploadBase64Img(request, base64Str, imgName, 
				appId, tenantId, classifyCode1, classifyCode2, 
				thumbnail1Width, thumbnail1Height, thumbnail2Width, thumbnail2Height, loginId);

		Map<String,Object> fileInfo = new HashMap<String,Object>();
		fileInfo.put("fileName", imgName);
		fileInfo.put("id", uploadFile.getId());
		fileInfo.put("accessId", uploadFile.getAccessId());
		fileInfo.put("fileSize", uploadFile.getFileBytes());
		result.add(fileInfo);  

		response.setContentType("text/json;charset=utf-8");
		response.setHeader("Pragma", "No-cache");
		response.setDateHeader("Expires", 0);
		response.setHeader("Cache-Control", "no-cache");
		String resultString = TJSON.toJSONString(result);
		try(PrintWriter out = response.getWriter()){
			out.println(resultString);
			out.flush();
		}
		return NullValue.value;
	}

	@Path(value="testupload", httpGet=true)
	public ViewModel testupload() {
		Map<String, Object> params = this.getRequestParameters();
		return new FtlViewModel("view/test/index2.html", params);
	}

}
